home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / rcs4 / source / rcssyn.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-03-08  |  17.7 KB  |  578 lines

  1. /*
  2.  *                     RCS file input
  3.  */
  4. #ifndef lint
  5. static char rcsid[]= "$Id: rcssyn.c 5.2 90/07/15 11:35:24 ROOT_DOS Release $ Purdue CS";
  6. #endif
  7. /*********************************************************************************
  8.  *                       Syntax Analysis.
  9.  *                       Keyword table
  10.  *                       Testprogram: define SYNDB
  11.  *                       Compatibility with Release 2: define COMPAT2
  12.  *********************************************************************************
  13.  */
  14.  
  15. /* Copyright (C) 1982, 1988, 1989 Walter Tichy
  16.    Distributed under license by the Free Software Foundation, Inc.
  17.  
  18. This file is part of RCS.
  19.  
  20. RCS is free software; you can redistribute it and/or modify
  21. it under the terms of the GNU General Public License as published by
  22. the Free Software Foundation; either version 1, or (at your option)
  23. any later version.
  24.  
  25. RCS is distributed in the hope that it will be useful,
  26. but WITHOUT ANY WARRANTY; without even the implied warranty of
  27. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  28. GNU General Public License for more details.
  29.  
  30. You should have received a copy of the GNU General Public License
  31. along with RCS; see the file COPYING.  If not, write to
  32. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  33.  
  34. Report problems and direct all questions to:
  35.  
  36.     rcs-bugs@cs.purdue.edu
  37.  
  38. */
  39.  
  40.  
  41. /* $Log:    rcssyn.c $
  42.  * Revision 5.2  90/07/15  11:35:24  ROOT_DOS
  43.  * checked in with -k by ROOT_DOS at 91.02.07.11.45.42.
  44.  * 
  45.  * Revision 5.2  90/07/15  11:35:24  ROOT_DOS
  46.  * DOS version of RCS 4.0 checked in for MODS
  47.  * by lfk@athena.mit.edu
  48.  * Also update to MSC 6.0
  49.  * 
  50.  * Revision 4.6  89/05/01  15:13:32  narten
  51.  * changed copyright header to reflect current distribution rules
  52.  * 
  53.  * Revision 4.5  88/11/08  12:00:37  narten
  54.  * changes from  eggert@sm.unisys.com (Paul Eggert)
  55.  * 
  56.  * Revision 4.5  88/08/09  19:13:21  eggert
  57.  * Allow cc -R; remove lint.
  58.  * 
  59.  * Revision 4.4  87/12/18  11:46:16  narten
  60.  * more lint cleanups (Guy Harris)
  61.  * 
  62.  * Revision 4.3  87/10/18  10:39:36  narten
  63.  * Updating version numbers. Changes relative to 1.1 actually relative to
  64.  * 4.1
  65.  * 
  66.  * Revision 1.3  87/09/24  14:00:49  narten
  67.  * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
  68.  * warnings)
  69.  * 
  70.  * Revision 1.2  87/03/27  14:22:40  jenkins
  71.  * Port to suns
  72.  * 
  73.  * Revision 1.1  84/01/23  14:50:40  kcs
  74.  * Initial revision
  75.  * 
  76.  * Revision 4.1  83/03/28  11:38:49  wft
  77.  * Added parsing and printing of default branch.
  78.  * 
  79.  * Revision 3.6  83/01/15  17:46:50  wft
  80.  * Changed readdelta() to initialize selector and log-pointer.
  81.  * Changed puttree to check for selector==DELETE; putdtext() uses DELNUMFORM.
  82.  *
  83.  * Revision 3.5  82/12/08  21:58:58  wft
  84.  * renamed Commentleader to Commleader.
  85.  *
  86.  * Revision 3.4  82/12/04  13:24:40  wft
  87.  * Added routine gettree(), which updates keeplock after reading the
  88.  * delta tree.
  89.  *
  90.  * Revision 3.3  82/11/28  21:30:11  wft
  91.  * Reading and printing of Suffix removed; version COMPAT2 skips the
  92.  * Suffix for files of release 2 format. Fixed problems with printing nil.
  93.  *
  94.  * Revision 3.2  82/10/18  21:18:25  wft
  95.  * renamed putdeltatext to putdtext.
  96.  *
  97.  * Revision 3.1  82/10/11  19:45:11  wft
  98.  * made sure getc() returns into an integer.
  99.  */
  100.  
  101.  
  102.  
  103. /*
  104. #define COMPAT2
  105. /* version COMPAT2 reads files of the format of release 2 and 3, but
  106.  * generates files of release 3 format. Need not be defined if no
  107.  * old RCS files generated with release 2 exist.
  108.  */
  109. /*
  110. #define SYNDB
  111. /* version SYNDB is for debugging the syntax analysis for RCS files.
  112.  * SYNDB performs additional error checks.
  113.  */
  114. /*
  115. #define SYNTEST
  116. /* version SYNTEST inputs a RCS file and then prints out its internal
  117.  * data structures.
  118. */
  119.  
  120. #include "rcsbase.h"
  121. extern FILE * finptr;        /*RCS input file*/
  122. extern char * getid();
  123. extern struct hshentry * getnum();
  124. extern int    getkey();
  125. extern int    getlex();
  126. extern        readstring();
  127. extern        savestring();
  128.  
  129. /* forward */
  130. char * getkeyval();
  131.  
  132. /* keyword table */
  133.  
  134. char Kaccess[]   = "access";
  135. char Kauthor[]   = "author";
  136. char Kbranch[]   = "branch";
  137. char Kbranches[] = "branches";
  138. char Kcomment[]  = "comment";
  139. char Kdate[]     = "date";
  140. char Kdesc[]     = "desc";
  141. char Khead[]     = "head";
  142. char Klocks[]    = "locks";
  143. char Klog[]      = "log";
  144. char Knext[]     = "next";
  145. char Kstate[]    = "state";
  146. char Kstrict[]   = "strict";
  147. #ifdef COMPAT2
  148. char Ksuffix[]   = "suffix";
  149. #endif
  150. char Ksymbols[]  = "symbols";
  151. char Ktext[]     = "text";
  152.  
  153. #define COMMLENGTH 20
  154. char              Commleader[COMMLENGTH];
  155. char            * Comment;
  156. struct access   * AccessList;
  157. struct access   * LastAccess;
  158. struct assoc    * Symbols;
  159. struct assoc    * LastSymbol;
  160. struct lock     * Locks;
  161. struct lock     * LastLock;
  162. int               StrictLocks;
  163. struct hshentry * Head;
  164. struct hshentry * Dbranch;
  165. int               TotalDeltas;
  166.  
  167.  
  168.  
  169. getadmin()
  170. /* Function: Reads an <admin> and initializes the globals
  171.  * AccessList, LastAccess, Symbols, LastSymbol,
  172.  * Locks, LastLock, StrictLocks, Head, Comment, TotalDeltas;
  173.  */
  174. {
  175.         register char   * id;
  176.         struct access   * newaccess;
  177.         struct assoc    * newassoc;
  178.         struct lock     * newlock;
  179.         struct hshentry * delta;
  180.  
  181.         Comment="";
  182.         AccessList=LastAccess=nil;
  183.         Symbols=LastSymbol=nil;
  184.         Locks=LastLock=nil;
  185.         Dbranch = Head = nil;
  186.         TotalDeltas=0;
  187.  
  188.         if (!getkey(Khead)) fatserror("Missing head");
  189.         Head=getnum();
  190. #       ifdef SYNDB
  191.         if (Head&&((countnumflds(Head->num)%2)!=0))
  192.                 serror("Delta number required for head");
  193. #       endif
  194.         if (!getlex(SEMI)) serror("Missing ';' after head");
  195.  
  196.         if (getkey(Kbranch)) { /* optional */
  197.                 Dbranch=getnum();
  198.                 if (!getlex(SEMI)) serror("Missing ';' after branch list");
  199.         }
  200.  
  201.  
  202. #ifdef COMPAT2
  203.         /* read suffix. Only in release 2 format */
  204.         if (getkey(Ksuffix)) {
  205.                 if (nexttok==STRING) {
  206.                         readstring(); nextlex(); /*through away the suffix*/
  207.                 } elsif(nexttok==ID) {
  208.                         nextlex();
  209.                 }
  210.                 if (!getlex(SEMI)) serror("Missing ';' after %s",Ksuffix);
  211.         }
  212. #endif
  213.  
  214.         if (!getkey(Kaccess)) fatserror("Missing access list");
  215.         while (id=getid()) {
  216.                 newaccess = (struct access *)talloc(sizeof(struct access));
  217.                 newaccess->login = id;
  218.                 newaccess->nextaccess = nil;
  219.                 if (AccessList == nil) {
  220.                         AccessList=LastAccess=newaccess;
  221.                 } else {
  222.                         LastAccess=LastAccess->nextaccess=newaccess;
  223.                 }
  224.         }
  225.         if (!getlex(SEMI)) serror("Missing ';' after access list");
  226.  
  227.         if (!getkey(Ksymbols)) fatserror("Missing symbols");
  228.         while (id = getid()) {
  229.                 if (!getlex(COLON))
  230.                         serror("Missing ':' in symbolic name definition");
  231.                 if (!(delta=getnum())) {
  232.                         serror("Missing number in symbolic name definition");
  233.                 } else { /*add new pair to association list*/
  234.                         newassoc=(struct assoc *)talloc(sizeof(struct assoc));
  235.                         newassoc->symbol=id;
  236.                         newassoc->delta=delta;
  237.                         newassoc->nextassoc=nil;
  238.                         if (Symbols == nil) {
  239.                                 Symbols=LastSymbol=newassoc;
  240.                         } else {
  241.                                 LastSymbol=LastSymbol->nextassoc=newassoc;
  242.                         }
  243.                 }
  244.         }
  245.         if (!getlex(SEMI)) serror("Missing ';' after symbolic names");
  246.  
  247.         if (!getkey(Klocks)) serror("Missing locks");
  248.         while (id = getid()) {
  249.                 if (!getlex(COLON))
  250.                         serror("Missing ':' in lock");
  251.                 if (!(delta=getnum())) {
  252.                         serror("Missing number in lock");
  253.                 } else { /*add new pair to lock list*/
  254. #                       ifdef SYNDB
  255.                         if ((countnumflds(delta->num)%2)!=0)
  256.                                 serror("Delta number required for lock");
  257. #                       endif
  258.                         newlock=(struct lock *)talloc(sizeof(struct lock));
  259.                         newlock->login=id;
  260.                         newlock->delta=delta;
  261.                         newlock->nextlock=nil;
  262.                         if (Locks == nil) {
  263.                                 Locks=LastLock=newlock;
  264.                         } else {
  265.                                 LastLock=LastLock->nextlock=newlock;
  266.                         }
  267.                 }
  268.         }
  269.         if (!getlex(SEMI)) serror("Missing ';' after locks");
  270.         if (!getkey(Kstrict)) {
  271.                 StrictLocks = false;
  272.         } else {
  273.                 StrictLocks = true;
  274.                 if (!getlex(SEMI)) serror("Missing ';' after keyword %s",Kstrict);
  275.         }
  276.         if (getkey(Kcomment) && (nexttok==STRING)) {
  277.                 VOID savestring(Commleader,COMMLENGTH);nextlex();
  278.                 Comment=Commleader;
  279.                 if (!getlex(SEMI)) serror("Missing ';' after %s",Kcomment);
  280.         }
  281. }
  282.  
  283.  
  284.  
  285. getdelta()
  286. /* Function: reads a delta block.
  287.  * returns false if the current block does not start with a number.
  288.  */
  289. {
  290.         register struct hshentry * Delta, * num;
  291.         struct branchhead * LastBranch, * NewBranch;
  292.  
  293.         if (!(Delta=getnum())) return false;
  294. #       ifdef SYNDB
  295.         if ((countnumflds(Delta->num)%2)!=0)
  296.                 serror("Delta number required");
  297. #       endif
  298.  
  299.         hshenter = false; /*Don't enter dates into hashtable*/
  300.         Delta->date = getkeyval(Kdate, NUM, false);
  301.         hshenter=true;    /*reset hshenter for revision numbers.*/
  302.  
  303.         Delta->author = getkeyval(Kauthor, ID, false);
  304.  
  305.         Delta->state = getkeyval(Kstate, ID, true);
  306.  
  307.         if (!getkey(Kbranches)) fatserror("Missing branches");
  308.         Delta->branches = LastBranch=nil;
  309.         while (num=getnum()) {
  310. #               ifdef SYNDB
  311.                 if ((countnumflds(num->num)%2)!=0)
  312.                         serror("Delta number required");
  313. #               endif
  314.                 NewBranch = (struct branchhead *)talloc(sizeof(struct branchhead));
  315.                 NewBranch->hsh = num;
  316.                 NewBranch->nextbranch = nil;
  317.                 if (LastBranch == nil) {
  318.                         Delta->branches=LastBranch=NewBranch;
  319.                 } else {
  320.                         LastBranch=LastBranch->nextbranch=NewBranch;
  321.                 }
  322.         }
  323.         if (!getlex(SEMI)) serror("Missing ';' after branches");
  324.  
  325.         if (!getkey(Knext)) fatserror("Missing next");
  326.         Delta->next=num=getnum();
  327. #       ifdef SYNDB
  328.         if (num&&((countnumflds(num->num)%2)!=0))
  329.                 serror("Delta number required");
  330. #       endif
  331.         if (!getlex(SEMI)) serror("Missing ';' after next");
  332.         Delta->log=Delta->lockedby = nil;
  333.         Delta->selector = '\0';
  334.         TotalDeltas++;
  335.         return (true);
  336. }
  337.  
  338.  
  339. gettree()
  340. /* Function: Reads in the delta tree with getdelta(), then
  341.  * updates the lockedby fields.
  342.  */
  343. {       struct lock * currlock;
  344.         while (getdelta());
  345.         currlock=Locks;
  346.         while (currlock) {
  347.                 currlock->delta->lockedby = currlock->login;
  348.                 currlock = currlock->nextlock;
  349.         }
  350. }
  351.  
  352.  
  353. getdesc(prdesc)
  354. int  prdesc;
  355. /* Function: read in descriptive text
  356.  * nexttok is not advanced afterwards.
  357.  * if prdesc==true, the text is printed to stdout.
  358.  */
  359. {
  360.  
  361.         if (!getkey(Kdesc) || (nexttok!=STRING)) fatserror("Missing descriptive text");
  362.         if (prdesc)
  363.                 printstring();  /*echo string*/
  364.         else    readstring();   /*skip string*/
  365. }
  366.  
  367.  
  368.  
  369.  
  370.  
  371.  
  372. char * getkeyval(keyword, token, optional)
  373. enum tokens token; char * keyword; int optional;
  374. /* reads a pair of the form
  375.  * <keyword> <token> ;
  376.  * where token is one of <id> or <num>. optional indicates whether
  377.  * <token> is optional. A pointer to
  378.  * the acutal character string of <id> or <num) is returned.
  379.  * Getkeyval terminates the program on missing keyword or token, continues
  380.  * on missing ;.
  381.  */
  382. {
  383.         register char * val;
  384.  
  385.         if (!getkey(keyword)) {
  386.                 fatserror("Missing %s", keyword);
  387.         }
  388.         if (nexttok==token) {
  389.                 val = NextString;
  390.                 nextlex();
  391.         } else {
  392.                 if (!optional) {fatserror("Missing %s", keyword); }
  393.                 else val = nil;
  394.         }
  395.         if (!getlex(SEMI)) serror("Missing ';' after %s",keyword);
  396.         return(val);
  397. }
  398.  
  399.  
  400.  
  401.  
  402. putadmin(fout)
  403. register FILE * fout;
  404. /* Function: Print the <admin> node read with getadmin() to file fout.
  405.  * Assumption: Variables AccessList, Symbols, Locks, StrictLocks,
  406.  * and Head have been set.
  407.  */
  408. {       struct assoc  * curassoc;
  409.         struct lock   * curlock;
  410.         struct access * curaccess;
  411.         register char * sp;
  412.  
  413.         VOID fputs(Khead,fout); VOID fputs("     ",fout);
  414.         if (Head) VOID fputs(Head->num,fout);
  415.  
  416.         VOID fprintf(fout,";\n%s   ",Kbranch);
  417.         if (Dbranch) VOID fputs(Dbranch->num,fout);
  418.  
  419.         VOID fprintf(fout,";\n%s  ",Kaccess);
  420.         curaccess = AccessList;
  421.         if (curaccess==nil) VOID putc(' ',fout);
  422.         while (curaccess) {
  423.                VOID putc(' ',fout);
  424.                VOID fputs(curaccess->login,fout);
  425.                curaccess = curaccess->nextaccess;
  426.         }
  427.         VOID fprintf(fout,";\n%s ",Ksymbols);
  428.         curassoc = Symbols;
  429.         if (curassoc==nil) VOID putc(' ',fout);
  430.         while (curassoc) {
  431.                VOID fprintf(fout," %s:%s",curassoc->symbol, curassoc->delta->num);
  432.                curassoc = curassoc->nextassoc;
  433.         }
  434.         VOID fprintf(fout,";\n%s   ",Klocks);
  435.         curlock = Locks;
  436.         if (curlock==nil) VOID putc(' ',fout);
  437.         while (curlock) {
  438.                VOID fprintf(fout," %s:%s",curlock->login, curlock->delta->num);
  439.                curlock = curlock->nextlock;
  440.         }
  441.         if (StrictLocks) VOID fprintf(fout,"; %s",Kstrict);
  442.         VOID fprintf(fout,";\n%s  %c",Kcomment,SDELIM);
  443.         if((sp=Comment)!=nil) {
  444.                while (*sp) if (putc(*sp++,fout)==SDELIM) VOID putc(SDELIM,fout);
  445.         }
  446.         VOID fprintf(fout,"%c;\n\n",SDELIM);
  447. }
  448.  
  449.  
  450.  
  451.  
  452. putdelta(node,fout)
  453. register struct hshentry * node;
  454. register FILE * fout;
  455. /* Function: prints a <delta> node to fout;
  456.  */
  457. {      struct branchhead * nextbranch;
  458.  
  459.         if (node == nil) return;
  460.  
  461.         VOID fprintf(fout,"\n%s\n",node->num);
  462.         VOID fprintf(fout,"%s     %s;  %s %s;  %s ",
  463.                 Kdate,node->date,Kauthor,node->author,Kstate);
  464.         if (node->state!=nil) VOID fputs(node->state,fout);
  465.         VOID fputs(";\nbranches",fout);
  466.         nextbranch = node->branches;
  467.         if (nextbranch==nil) VOID putc(' ',fout);
  468.         while (nextbranch) {
  469.                VOID putc(' ',fout);
  470.                VOID fputs(nextbranch->hsh->num,fout);
  471.                nextbranch = nextbranch->nextbranch;
  472.         }
  473.  
  474.         VOID fprintf(fout,";\n%s     ",Knext);
  475.         if (node->next!=nil) VOID fputs(node->next->num,fout);
  476.         VOID fputs(";\n",fout);
  477.  
  478. }
  479.  
  480.  
  481.  
  482.  
  483. puttree(root,fout)
  484. struct hshentry * root;
  485. register FILE * fout;
  486. /* Function: prints the delta tree in preorder to fout, starting with root.
  487.  */
  488. {       struct branchhead * nextbranch;
  489.  
  490.         if (root==nil) return;
  491.  
  492.         if (root->selector !=DELETE)putdelta(root,fout);
  493.         /* selector DELETE means deleted; set by rcs -o */
  494.  
  495.         puttree(root->next,fout);
  496.  
  497.         nextbranch = root->branches;
  498.         while (nextbranch) {
  499.              puttree(nextbranch->hsh,fout);
  500.              nextbranch = nextbranch->nextbranch;
  501.         }
  502. }
  503.  
  504.  
  505.  
  506. int putdtext(num,log,srcfilename,fout)
  507. char * num, * log, * srcfilename; FILE * fout;
  508. /* Function: write a deltatext-node to fout.
  509.  * num points to the deltanumber, log to the logmessage, and
  510.  * sourcefile contains the text. Doubles up all SDELIMs in both the
  511.  * log and the text; Makes sure the log message ends in \n.
  512.  * returns false on error.
  513.  */
  514. {
  515.         register char * sp;
  516.     register int c;
  517.         register FILE * fin;
  518.  
  519.         VOID fprintf(fout,DELNUMFORM,num,Klog);
  520.         /* put log */
  521.         VOID putc(SDELIM,fout);
  522.         sp=log;
  523.         while (*sp) if (putc(*sp++,fout)==SDELIM) VOID putc(SDELIM,fout);
  524.         if (*(sp-1)!='\n') VOID putc('\n', fout); /*append \n if necessary*/
  525.         /* put text */
  526.         VOID fprintf(fout, "%c\n%s\n%c",SDELIM,Ktext,SDELIM);
  527.         if ((fin=fopen(srcfilename,"r"))==NULL) {
  528.                 error("Can't open source file %s",srcfilename);
  529.                 return false;
  530.         }
  531.         while ((c=fgetc(fin))!=EOF) {
  532.                 if (c==SDELIM) VOID putc(SDELIM,fout);   /*double up SDELIM*/
  533.                 VOID putc(c,fout);
  534.         }
  535.         VOID putc(SDELIM,fout); VOID putc('\n',fout);
  536.         VOID fclose(fin);
  537.         return true;
  538. }
  539.  
  540.  
  541.  
  542. #ifdef SYNTEST
  543.  
  544. main(argc,argv)
  545. int argc; char * argv[];
  546. {
  547.  
  548.         cmdid = "syntest";
  549.         if (argc<2) {
  550.                 VOID fputs("No input file\n",stderr);
  551.                 exit(-1);
  552.         }
  553.         if ((finptr=fopen(argv[1], "r")) == NULL) {
  554.                 faterror("Can't open input file %s\n",argv[1]);
  555.         }
  556.         Lexinit();
  557.         getadmin();
  558.         putadmin(stdout);
  559.  
  560.         gettree();
  561.         puttree(Head,stdout);
  562.  
  563.         getdesc(true);
  564.  
  565.         if (nextlex(),nexttok!=EOFILE) {
  566.                 fatserror("Syntax error");
  567.         }
  568.         exit(0);
  569. }
  570.  
  571.  
  572. cleanup(){}
  573. /*dummy*/
  574.  
  575.  
  576. #endif
  577.  
  578.